package com.wlf.server.common.service;

import cn.hutool.core.lang.Dict;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.wlf.server.common.em.DictKey;
import com.wlf.server.common.entity.OrganUser;
import com.wlf.server.common.entity.SysOrgan;
import com.wlf.server.common.entity.SysRegion;
import com.wlf.server.common.mapper.SysOrganMapper;
import com.wlf.server.web.dto.MappingDTO;
import com.wlf.server.web.dto.OrganDTO;
import com.wlf.server.web.dto.ParamPage;
import com.wlf.server.web.util.AjaxBean;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class SysOrganService extends ServiceImpl<SysOrganMapper, SysOrgan> {
    @Resource
    MappingDTO mappingDTO;
    @Resource
    SysRegionService regionService;
    @Resource
    SysDictService dictService;

    public AjaxBean parentList(){
        List<SysOrgan> organs = this.list();
        SysOrgan organ = new SysOrgan();
        organ.setPid("0");
        organ.setId("0");
        organ.setName("根机构");
        organs.add(organ);
        List<SysRegion> regions = regionService.list();
        TreeNodeConfig tConfig = new TreeNodeConfig();
        tConfig.setWeightKey("sort");
        tConfig.setIdKey("value");
        tConfig.setChildrenKey("children");
        tConfig.setNameKey("label");
        Dict dict = Dict.create();
        dict.set("pidOptions",this.getTree(organs));
        dict.set("regionIdOptions",regionService.getTree(regions, tConfig));
        dict.set("typeOptions",dictService.getList(DictKey.organ_type));
        return AjaxBean.getOkData(dict);
    }

    /**
     * 主数据
     */
    public AjaxBean list(OrganDTO organDTO){
        LambdaQueryWrapper<SysOrgan> wrapper = new LambdaQueryWrapper<>();
        List<SysOrgan> list = this.list(wrapper);
        return AjaxBean.getOkData(getTree(list));
    }

    public AjaxBean get(String id){
        OrganDTO organDTO = mappingDTO.toDTO(this.getById(id));
        organDTO.setRegionDTO(mappingDTO.toDTO(regionService.getById(organDTO.getRegionId())));
        organDTO.setTypeName(dictService.getMap(DictKey.organ_type).get(organDTO.getType()));
        return AjaxBean.getOkData(organDTO);
    }

    public AjaxBean saveOrUpdate(OrganDTO organDTO){
        return AjaxBean.getByBool(Db.saveOrUpdate(mappingDTO.to(organDTO)));
    }

    /**
     * 删除
     * @param id 单个ID
     */
    public AjaxBean del(String id){
        ArrayList<String> organIds = new ArrayList<>();
        getOrganIds(id,organIds);
        // 这里需要做递归删除
        return AjaxBean.getByBool(Db.removeByIds(organIds,this.entityClass));
    }
    /**
     * 递归查当前区域的所有子区域ID
     */
    public void getOrganIds(String id,List<String> ids){
        ids.add(id);
        // 此处换成JDBC会更好
        List<SysOrgan> list = this.list(new LambdaQueryWrapper<SysOrgan>().eq(SysOrgan::getPid, id));
        if (ObjectUtil.isNotEmpty(list)){
            for (SysOrgan organ : list) {
                getOrganIds(organ.getId(),ids);
            }
        }
    }

    /**
     * 获取树形数据
     */
    public List<Tree<String>> getTree(List<SysOrgan> list){
        TreeNodeConfig tConfig = new TreeNodeConfig();
        tConfig.setChildrenKey("children");
        tConfig.setNameKey("label");
        tConfig.setWeightKey("sort");
        //转换器
        return TreeUtil.build(list, "0", tConfig,
                (l, tree) -> {
                    tree.setId(l.getId());
                    tree.setParentId(l.getPid());
                    tree.setWeight(l.getSort());
                    tree.setName(l.getName());
                    tree.putExtra("status",l.getStatus());
                    tree.putExtra("label",l.getName());
                    tree.putExtra("value",l.getId());
                    tree.putExtra("type",l.getType());
                    tree.putExtra("typeName",dictService.getMap(DictKey.organ_type).get(l.getType()));
                });
    }

    /**
     * 根据区域ID查出其下所有的机构信息
     */
    public AjaxBean getOrganByRegionId(String id, OrganDTO organDTO, ParamPage paramPage){
        // 区域ID
        ArrayList<String> regionIds = new ArrayList<>();
        // 是否查看子集
        if (organDTO.getShowChildren()){
            regionService.getRegionIds(id,regionIds);
        } else {
            // 不查看子集
            regionIds.add(id);
        }
        // 获取其下所有的区域信息包括子集
        List<SysRegion> sysRegions = regionService.listByIds(regionIds);
        // 一个Map，key为区域ID，value为区域实体类
        Dict regionIdAndRegion = Dict.create();
        sysRegions.forEach( i -> regionIdAndRegion.set(i.getId(),i));

        LambdaQueryWrapper<SysOrgan> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(SysOrgan::getRegionId,regionIds);
        if (StrUtil.isNotBlank(organDTO.getName())){
            wrapper.like(SysOrgan::getName,organDTO.getName());
        }
        wrapper.orderByDesc(SysOrgan::getId);
        // 分页获取机构信息
        Page<SysOrgan> organPage = this.page(Page.of(paramPage.getCurrent(), paramPage.getSize()),wrapper);

        List<OrganDTO> organDTOS = mappingDTO.toOrganDTO(organPage.getRecords());

        for (OrganDTO i : organDTOS) {
            i.setRegionDTO(mappingDTO.toDTO((SysRegion) regionIdAndRegion.getBean(i.getRegionId())));
        }

        return AjaxBean.getOkPage(organPage).setData(organDTOS);
    }

    /**
     * 根据机构ID获取用户ID
     */
    public List<String> getUserIdsByOrganIds(List<String> organIds){
        List<OrganUser> organUsers = Db.lambdaQuery(OrganUser.class)
                .in(OrganUser::getOrganId, organIds).list();
        return organUsers
                .stream().map(OrganUser::getUserId).collect(Collectors.toList());
    }


    public List<OrganDTO> getOrganByUserId(String id){
        List<OrganUser> list = Db.lambdaQuery(OrganUser.class).eq(OrganUser::getUserId, id).list();
        List<String> organIds = list.stream().map(OrganUser::getOrganId).collect(Collectors.toList());
        List<SysOrgan> sysOrgans = this.listByIds(organIds);


        List<OrganDTO> organDTOS = mappingDTO.toOrganDTO(sysOrgans);
        for (OrganDTO i : organDTOS) {
            i.setRegionDTO(mappingDTO.toDTO(regionService.getById(i.getRegionId())));
        }

        return organDTOS;

    }
}
